public class STDPSynapse extends SynapseFramework implements ISynapse {
    private double aPlus = .0005 , aMinus = .000525 , tauPlus = 3 , tauMinus = 3 ;
    
    public STDPSynapse( INeuron pre , INeuron post , double w ) {
        super( pre , post , w ) ;
        String [ ] params = { "aPlus" , "aMinus" , "tauPlus" , "tauMinus" , "tauPrime" } ;
        parameterNames = params ;
    }
    
    public String getParam( String name ) {
        if ( name.equals( "aPlus" ) ) {
            return "" + aPlus ;
        } else if ( name.equals( "aMinus" ) ) {
            return "" + aMinus ;
        } else if ( name.equals( "tauMinus" ) ) {
            return "" + tauMinus ;
        } else if ( name.equals( "tauPlus" ) ) {
            return "" + tauPlus ;
        } else if ( name.equals( "tauPrime" ) ) {
            return "" + tauPrime ;
        } else {
            return null ;
        }
    }
    
    public void setParam( String name , String data ) {
        double value ;
        
        // all parameters are doubles
        try {
            value = Double.parseDouble( data ) ;
        } catch ( NumberFormatException e ) {
            // not a double; ignore the set request
            return ;
        }
        if ( name.equals( "aPlus" ) ) {
            aPlus = value ;
        } else if ( name.equals( "aMinus" ) ) {
            aMinus = value ;
        } else if ( name.equals( "tauMinus" ) ) {
            tauMinus = value ;
        } else if ( name.equals( "tauPlus" ) ) {
            tauPlus = value ;
        } else if ( name.equals( "tauPrime" ) ) {
            tauPrime = value ;
        }
    }
    
    public String getName( ) {
        return "Spike Timing Dependent Plasticity" ;
    }
    
    public ISynapse clone( INeuron pre , INeuron post , double s ) {
        STDPSynapse syn = new STDPSynapse( pre , post , s ) ;
        syn.setParam( getParams( ) ) ;
        return syn ;
    }
    
    public void advance( ) {
        double deltaT ;
        if ( post.lastSpike( ) == Double.NEGATIVE_INFINITY || pre.lastSpike( ) == Double.NEGATIVE_INFINITY ) {
            return ;
        }
        deltaT = post.lastSpike( ) - pre.lastSpike( ) ;
        if ( ! ( Double.isNaN( deltaT ) || Double.isInfinite( deltaT ) ) ) {
            if ( deltaT > 0 ) {
                w += aPlus * Math.exp( - deltaT / tauPlus ) ;
            } else {
                w += aMinus * Math.exp( deltaT / tauMinus ) ;
            }
        }
    }
}
